home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / ftp / RCS / glob.c,v < prev    next >
Encoding:
Text File  |  1991-11-12  |  11.6 KB  |  762 lines

  1. head     1.4;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.4
  10. date     91.11.11.19.46.48;  author shirriff;  state Exp;
  11. branches ;
  12. next     1.3;
  13.  
  14. 1.3
  15. date     90.10.27.13.48.42;  author shirriff;  state Exp;
  16. branches ;
  17. next     1.2;
  18.  
  19. 1.2
  20. date     88.07.20.14.26.39;  author ouster;  state Exp;
  21. branches ;
  22. next     1.1;
  23.  
  24. 1.1
  25. date     88.07.20.14.25.32;  author ouster;  state Exp;
  26. branches ;
  27. next     ;
  28.  
  29.  
  30. desc
  31. @@
  32.  
  33.  
  34. 1.4
  35. log
  36. @Fixed a problem with modifying buffers that weren't allocated.  This
  37. fix results in a memory leak, but it's small, so who cares.
  38. @
  39. text
  40. @/*
  41.  * Copyright (c) 1980 Regents of the University of California.
  42.  * All rights reserved.
  43.  *
  44.  * Redistribution and use in source and binary forms are permitted
  45.  * provided that the above copyright notice and this paragraph are
  46.  * duplicated in all such forms and that any documentation,
  47.  * advertising materials, and other materials related to such
  48.  * distribution and use acknowledge that the software was developed
  49.  * by the University of California, Berkeley.  The name of the
  50.  * University may not be used to endorse or promote products derived
  51.  * from this software without specific prior written permission.
  52.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  53.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  54.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  55.  */
  56.  
  57. #ifndef lint
  58. static char sccsid[] = "@@(#)glob.c    5.7 (Berkeley) 12/14/88";
  59. #endif /* not lint */
  60.  
  61. /*
  62.  * C-shell glob for random programs.
  63.  */
  64.  
  65. #include <sys/param.h>
  66. #include <sys/stat.h>
  67. #include <sys/dir.h>
  68.  
  69. #include <stdio.h>
  70. #include <errno.h>
  71. #include <pwd.h>
  72.  
  73. #define    QUOTE 0200
  74. #define    TRIM 0177
  75. #define    eq(a,b)        (strcmp(a, b)==0)
  76. #define    GAVSIZ        (NCARGS/6)
  77. #define    isdir(d)    ((d.st_mode & S_IFMT) == S_IFDIR)
  78.  
  79. static    char **gargv;        /* Pointer to the (stack) arglist */
  80. static    int gargc;        /* Number args in gargv */
  81. static    int gnleft;
  82. static    short gflag;
  83. static    int tglob();
  84. char    **glob();
  85. char    *globerr;
  86. char    *home;
  87. struct    passwd *getpwnam();
  88. extern    int errno;
  89. static    char *strspl(), *strend();
  90. char    *malloc(), *strcpy(), *strcat();
  91. char    **copyblk();
  92.  
  93. static    int globcnt;
  94.  
  95. char    *globchars = "`{[*?";
  96.  
  97. static    char *gpath, *gpathp, *lastgpathp;
  98. static    int globbed;
  99. static    char *entp;
  100. static    char **sortbas;
  101.  
  102. char **
  103. glob(v)
  104.     register char *v;
  105. {
  106.     char agpath[BUFSIZ];
  107.     char *agargv[GAVSIZ];
  108.     char *vv[2];
  109.     vv[0] = v;
  110.     vv[1] = 0;
  111.     gflag = 0;
  112.     rscan(vv, tglob);
  113.     if (gflag == 0)
  114.         return (copyblk(vv));
  115.  
  116.     globerr = 0;
  117.     gpath = agpath; gpathp = gpath; *gpathp = 0;
  118.     lastgpathp = &gpath[sizeof agpath - 2];
  119.     ginit(agargv); globcnt = 0;
  120.     collect(v);
  121.     if (globcnt == 0 && (gflag&1)) {
  122.         blkfree(gargv), gargv = 0;
  123.         return (0);
  124.     } else
  125.         return (gargv = copyblk(gargv));
  126. }
  127.  
  128. static
  129. ginit(agargv)
  130.     char **agargv;
  131. {
  132.  
  133.     agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0;
  134.     gnleft = NCARGS - 4;
  135. }
  136.  
  137. static
  138. collect(as)
  139.     register char *as;
  140. {
  141.     if (eq(as, "{") || eq(as, "{}")) {
  142.         Gcat(as, "");
  143.         sort();
  144.     } else
  145.         acollect(as);
  146. }
  147.  
  148. static
  149. acollect(as)
  150.     register char *as;
  151. {
  152.     register int ogargc = gargc;
  153.  
  154.     gpathp = gpath; *gpathp = 0; globbed = 0;
  155.     expand(as);
  156.     if (gargc != ogargc)
  157.         sort();
  158. }
  159.  
  160. static
  161. sort()
  162. {
  163.     register char **p1, **p2, *c;
  164.     char **Gvp = &gargv[gargc];
  165.  
  166.     p1 = sortbas;
  167.     while (p1 < Gvp-1) {
  168.         p2 = p1;
  169.         while (++p2 < Gvp)
  170.             if (strcmp(*p1, *p2) > 0)
  171.                 c = *p1, *p1 = *p2, *p2 = c;
  172.         p1++;
  173.     }
  174.     sortbas = Gvp;
  175. }
  176.  
  177. static
  178. expand(as)
  179.     char *as;
  180. {
  181.     register char *cs;
  182.     register char *sgpathp, *oldcs;
  183.     struct stat stb;
  184.  
  185.     sgpathp = gpathp;
  186.     cs = as;
  187.     if (*cs == '~' && gpathp == gpath) {
  188.         addpath('~');
  189.         for (cs++; letter(*cs) || digit(*cs) || *cs == '-';)
  190.             addpath(*cs++);
  191.         if (!*cs || *cs == '/') {
  192.             if (gpathp != gpath + 1) {
  193.                 *gpathp = 0;
  194.                 if (gethdir(gpath + 1))
  195.                     globerr = "Unknown user name after ~";
  196.                 (void) strcpy(gpath, gpath + 1);
  197.             } else
  198.                 (void) strcpy(gpath, home);
  199.             gpathp = strend(gpath);
  200.         }
  201.     }
  202.     while (!any(*cs, globchars)) {
  203.         if (*cs == 0) {
  204.             if (!globbed)
  205.                 Gcat(gpath, "");
  206.             else if (stat(gpath, &stb) >= 0) {
  207.                 Gcat(gpath, "");
  208.                 globcnt++;
  209.             }
  210.             goto endit;
  211.         }
  212.         addpath(*cs++);
  213.     }
  214.     oldcs = cs;
  215.     while (cs > as && *cs != '/')
  216.         cs--, gpathp--;
  217.     if (*cs == '/')
  218.         cs++, gpathp++;
  219.     *gpathp = 0;
  220.     if (*oldcs == '{') {
  221.         (void) execbrc(cs, ((char *)0));
  222.         return;
  223.     }
  224.     matchdir(cs);
  225. endit:
  226.     gpathp = sgpathp;
  227.     *gpathp = 0;
  228. }
  229.  
  230. static
  231. matchdir(pattern)
  232.     char *pattern;
  233. {
  234.     struct stat stb;
  235.     register struct direct *dp;
  236.     DIR *dirp;
  237.  
  238.     dirp = opendir(gpath);
  239.     if (dirp == NULL) {
  240.         if (globbed)
  241.             return;
  242.         goto patherr2;
  243.     }
  244.     if (fstat(dirp->dd_fd, &stb) < 0)
  245.         goto patherr1;
  246.     if (!isdir(stb)) {
  247.         errno = ENOTDIR;
  248.         goto patherr1;
  249.     }
  250.     while ((dp = readdir(dirp)) != NULL) {
  251.         if (dp->d_ino == 0)
  252.             continue;
  253.         if (match(dp->d_name, pattern)) {
  254.             Gcat(gpath, dp->d_name);
  255.             globcnt++;
  256.         }
  257.     }
  258.     closedir(dirp);
  259.     return;
  260.  
  261. patherr1:
  262.     closedir(dirp);
  263. patherr2:
  264.     globerr = "Bad directory components";
  265. }
  266.  
  267. static
  268. execbrc(p, s)
  269.     char *p, *s;
  270. {
  271.     char restbuf[BUFSIZ + 2];
  272.     register char *pe, *pm, *pl;
  273.     int brclev = 0;
  274.     char *lm, savec, *sgpathp;
  275.  
  276.     for (lm = restbuf; *p != '{'; *lm++ = *p++)
  277.         continue;
  278.     for (pe = ++p; *pe; pe++)
  279.     switch (*pe) {
  280.  
  281.     case '{':
  282.         brclev++;
  283.         continue;
  284.  
  285.     case '}':
  286.         if (brclev == 0)
  287.             goto pend;
  288.         brclev--;
  289.         continue;
  290.  
  291.     case '[':
  292.         for (pe++; *pe && *pe != ']'; pe++)
  293.             continue;
  294.         continue;
  295.     }
  296. pend:
  297.     brclev = 0;
  298.     for (pl = pm = p; pm <= pe; pm++)
  299.     switch (*pm & (QUOTE|TRIM)) {
  300.  
  301.     case '{':
  302.         brclev++;
  303.         continue;
  304.  
  305.     case '}':
  306.         if (brclev) {
  307.             brclev--;
  308.             continue;
  309.         }
  310.         goto doit;
  311.  
  312.     case ','|QUOTE:
  313.     case ',':
  314.         if (brclev)
  315.             continue;
  316. doit:
  317.         savec = *pm;
  318.         *pm = 0;
  319.         (void) strcpy(lm, pl);
  320.         (void) strcat(restbuf, pe + 1);
  321.         *pm = savec;
  322.         if (s == 0) {
  323.             sgpathp = gpathp;
  324.             expand(restbuf);
  325.             gpathp = sgpathp;
  326.             *gpathp = 0;
  327.         } else if (amatch(s, restbuf))
  328.             return (1);
  329.         sort();
  330.         pl = pm + 1;
  331.         if (brclev)
  332.             return (0);
  333.         continue;
  334.  
  335.     case '[':
  336.         for (pm++; *pm && *pm != ']'; pm++)
  337.             continue;
  338.         if (!*pm)
  339.             pm--;
  340.         continue;
  341.     }
  342.     if (brclev)
  343.         goto doit;
  344.     return (0);
  345. }
  346.  
  347. static
  348. match(s, p)
  349.     char *s, *p;
  350. {
  351.     register int c;
  352.     register char *sentp;
  353.     char sglobbed = globbed;
  354.  
  355.     if (*s == '.' && *p != '.')
  356.         return (0);
  357.     sentp = entp;
  358.     entp = s;
  359.     c = amatch(s, p);
  360.     entp = sentp;
  361.     globbed = sglobbed;
  362.     return (c);
  363. }
  364.  
  365. static
  366. amatch(s, p)
  367.     register char *s, *p;
  368. {
  369.     register int scc;
  370.     int ok, lc;
  371.     char *sgpathp;
  372.     struct stat stb;
  373.     int c, cc;
  374.  
  375.     globbed = 1;
  376.     for (;;) {
  377.         scc = *s++ & TRIM;
  378.         switch (c = *p++) {
  379.  
  380.         case '{':
  381.             return (execbrc(p - 1, s - 1));
  382.  
  383.         case '[':
  384.             ok = 0;
  385.             lc = 077777;
  386.             while (cc = *p++) {
  387.                 if (cc == ']') {
  388.                     if (ok)
  389.                         break;
  390.                     return (0);
  391.                 }
  392.                 if (cc == '-') {
  393.                     if (lc <= scc && scc <= *p++)
  394.                         ok++;
  395.                 } else
  396.                     if (scc == (lc = cc))
  397.                         ok++;
  398.             }
  399.             if (cc == 0)
  400.                 if (ok)
  401.                     p--;
  402.                 else
  403.                     return 0;
  404.             continue;
  405.  
  406.         case '*':
  407.             if (!*p)
  408.                 return (1);
  409.             if (*p == '/') {
  410.                 p++;
  411.                 goto slash;
  412.             }
  413.             s--;
  414.             do {
  415.                 if (amatch(s, p))
  416.                     return (1);
  417.             } while (*s++);
  418.             return (0);
  419.  
  420.         case 0:
  421.             return (scc == 0);
  422.  
  423.         default:
  424.             if (c != scc)
  425.                 return (0);
  426.             continue;
  427.  
  428.         case '?':
  429.             if (scc == 0)
  430.                 return (0);
  431.             continue;
  432.  
  433.         case '/':
  434.             if (scc)
  435.                 return (0);
  436. slash:
  437.             s = entp;
  438.             sgpathp = gpathp;
  439.             while (*s)
  440.                 addpath(*s++);
  441.             addpath('/');
  442.             if (stat(gpath, &stb) == 0 && isdir(stb))
  443.                 if (*p == 0) {
  444.                     Gcat(gpath, "");
  445.                     globcnt++;
  446.                 } else
  447.                     expand(p);
  448.             gpathp = sgpathp;
  449.             *gpathp = 0;
  450.             return (0);
  451.         }
  452.     }
  453. }
  454.  
  455. static
  456. Gmatch(s, p)
  457.     register char *s, *p;
  458. {
  459.     register int scc;
  460.     int ok, lc;
  461.     int c, cc;
  462.  
  463.     for (;;) {
  464.         scc = *s++ & TRIM;
  465.         switch (c = *p++) {
  466.  
  467.         case '[':
  468.             ok = 0;
  469.             lc = 077777;
  470.             while (cc = *p++) {
  471.                 if (cc == ']') {
  472.                     if (ok)
  473.                         break;
  474.                     return (0);
  475.                 }
  476.                 if (cc == '-') {
  477.                     if (lc <= scc && scc <= *p++)
  478.                         ok++;
  479.                 } else
  480.                     if (scc == (lc = cc))
  481.                         ok++;
  482.             }
  483.             if (cc == 0)
  484.                 if (ok)
  485.                     p--;
  486.                 else
  487.                     return 0;
  488.             continue;
  489.  
  490.         case '*':
  491.             if (!*p)
  492.                 return (1);
  493.             for (s--; *s; s++)
  494.                 if (Gmatch(s, p))
  495.                     return (1);
  496.             return (0);
  497.  
  498.         case 0:
  499.             return (scc == 0);
  500.  
  501.         default:
  502.             if ((c & TRIM) != scc)
  503.                 return (0);
  504.             continue;
  505.  
  506.         case '?':
  507.             if (scc == 0)
  508.                 return (0);
  509.             continue;
  510.  
  511.         }
  512.     }
  513. }
  514.  
  515. static
  516. Gcat(s1, s2)
  517.     register char *s1, *s2;
  518. {
  519.     register int len = strlen(s1) + strlen(s2) + 1;
  520.  
  521.     if (len >= gnleft || gargc >= GAVSIZ - 1)
  522.         globerr = "Arguments too long";
  523.     else {
  524.         gargc++;
  525.         gnleft -= len;
  526.         gargv[gargc] = 0;
  527.         gargv[gargc - 1] = strspl(s1, s2);
  528.     }
  529. }
  530.  
  531. static
  532. addpath(c)
  533.     char c;
  534. {
  535.  
  536.     if (gpathp >= lastgpathp)
  537.         globerr = "Pathname too long";
  538.     else {
  539.         *gpathp++ = c;
  540.         *gpathp = 0;
  541.     }
  542. }
  543.  
  544. static
  545. rscan(t, f)
  546.     register char **t;
  547.     int (*f)();
  548. {
  549.     register char *p, c;
  550.  
  551.     while (p = *t++) {
  552.         if (f == tglob)
  553.             if (*p == '~')
  554.                 gflag |= 2;
  555.             else if (eq(p, "{") || eq(p, "{}"))
  556.                 continue;
  557.         while (c = *p++)
  558.             (*f)(c);
  559.     }
  560. }
  561. /*
  562. static
  563. scan(t, f)
  564.     register char **t;
  565.     int (*f)();
  566. {
  567.     register char *p, c;
  568.  
  569.     while (p = *t++)
  570.         while (c = *p)
  571.             *p++ = (*f)(c);
  572. } */
  573.  
  574. static
  575. tglob(c)
  576.     register char c;
  577. {
  578.  
  579.     if (any(c, globchars))
  580.         gflag |= c == '{' ? 2 : 1;
  581.     return (c);
  582. }
  583. /*
  584. static
  585. trim(c)
  586.     char c;
  587. {
  588.  
  589.     return (c & TRIM);
  590. } */
  591.  
  592.  
  593. letter(c)
  594.     register char c;
  595. {
  596.  
  597.     return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_');
  598. }
  599.  
  600. digit(c)
  601.     register char c;
  602. {
  603.  
  604.     return (c >= '0' && c <= '9');
  605. }
  606.  
  607. any(c, s)
  608.     register int c;
  609.     register char *s;
  610. {
  611.  
  612.     while (*s)
  613.         if (*s++ == c)
  614.             return(1);
  615.     return(0);
  616. }
  617. blklen(av)
  618.     register char **av;
  619. {
  620.     register int i = 0;
  621.  
  622.     while (*av++)
  623.         i++;
  624.     return (i);
  625. }
  626.  
  627. char **
  628. blkcpy(oav, bv)
  629.     char **oav;
  630.     register char **bv;
  631. {
  632.     register char **av = oav;
  633.  
  634.     while (*bv != 0) {
  635.         *av = (char *)malloc(strlen(*bv)+1);
  636.         strcpy(*av,*bv);
  637.         av++;
  638.         bv++;
  639.     }
  640.     *av = 0;
  641.     return (oav);
  642. }
  643.  
  644. blkfree(av0)
  645.     char **av0;
  646. {
  647.     register char **av = av0;
  648.  
  649.     while (*av)
  650.         free(*av++);
  651. }
  652.  
  653. static
  654. char *
  655. strspl(cp, dp)
  656.     register char *cp, *dp;
  657. {
  658.     register char *ep = malloc((unsigned)(strlen(cp) + strlen(dp) + 1));
  659.  
  660.     if (ep == (char *)0)
  661.         fatal("Out of memory");
  662.     (void) strcpy(ep, cp);
  663.     (void) strcat(ep, dp);
  664.     return (ep);
  665. }
  666.  
  667. char **
  668. copyblk(v)
  669.     register char **v;
  670. {
  671.     register char **nv = (char **)malloc((unsigned)((blklen(v) + 1) *
  672.                         sizeof(char **)));
  673.     if (nv == (char **)0)
  674.         fatal("Out of memory");
  675.  
  676.     return (blkcpy(nv, v));
  677. }
  678.  
  679. static
  680. char *
  681. strend(cp)
  682.     register char *cp;
  683. {
  684.  
  685.     while (*cp)
  686.         cp++;
  687.     return (cp);
  688. }
  689. /*
  690.  * Extract a home directory from the password file
  691.  * The argument points to a buffer where the name of the
  692.  * user whose home directory is sought is currently.
  693.  * We write the home directory of the user back there.
  694.  */
  695. gethdir(home)
  696.     char *home;
  697. {
  698.     register struct passwd *pp = getpwnam(home);
  699.  
  700.     if (!pp || home + strlen(pp->pw_dir) >= lastgpathp)
  701.         return (1);
  702.     (void) strcpy(home, pp->pw_dir);
  703.     return (0);
  704. }
  705. @
  706.  
  707.  
  708. 1.3
  709. log
  710. @New revision.
  711. @
  712. text
  713. @d595 7
  714. a601 2
  715.     while (*av++ = *bv++)
  716.         continue;
  717. @
  718.  
  719.  
  720. 1.2
  721. log
  722. @Add declarations for forward references, in order to avoid gcc complaints.
  723. @
  724. text
  725. @d6 10
  726. a15 5
  727.  * provided that this notice is preserved and that due credit is given
  728.  * to the University of California at Berkeley. The name of the University
  729.  * may not be used to endorse or promote products derived from this
  730.  * software without specific prior written permission. This software
  731.  * is provided ``as is'' without express or implied warranty.
  732. d19 1
  733. a19 1
  734. static char sccsid[] = "@@(#)glob.c    5.3 (Berkeley) 3/14/88";
  735. d41 2
  736. a42 2
  737. static    short gargc;        /* Number args in gargv */
  738. static    short gnleft;
  739. a62 7
  740. /*
  741.  * Forward references to procedures declared later in this file:
  742.  */
  743.  
  744. extern int acollect(), addpath(), amatch(), collect(), execbrc();
  745. extern int expand(), Gcat(), ginit(), match(), matchdir(), rscan(), sort();
  746.  
  747. a606 1
  748.     free((char *)av0);
  749. d656 1
  750. a656 1
  751.     if (pp == 0)
  752. @
  753.  
  754.  
  755. 1.1
  756. log
  757. @Initial revision
  758. @
  759. text
  760. @d58 7
  761. @
  762.